/*----------------------------------------------------------------------------
 * Copyright (c) <2019-2020>, <Huawei Technologies Co., Ltd>
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *---------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei OMIP(belong to OMSIS) may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 *---------------------------------------------------------------------------*/

#include "securec.h"
#include "omip.h"
#include "omip_log.h"
#include "hardware_com.h"
#include "read_and_write_flash.h"

omip_log_level g_omip_log_level = OMIP_INFO; //OMIP_INFO   OMIP_ERROR

static char g_omip_print_buf[OMIP_PRINT_BUF+32+1];

/* g_start_addr_cache is to record write log to cache/flash start address*/
static unsigned int g_start_addr_cache = 0;
static unsigned int g_start_addr_flash = 0;

/*自纪元 Epoch（1970-01-01 00:00:00 UTC）起经过的时间，以秒为单位*/
static long long g_time_utc_sec = 0;

/* omip malloc 32k memory to store log info */
uint8_t *g_omip_log_buffer = NULL;

zone_info g_log_buffer_zone_info = {
	.id = LOGRECORD_ZONE,
	.start_address = 0x00000000,
	.end_address = 0x00000000 + (OMIP_FLASH_SECTOR_SIZE * OMIP_LOG_BUFFER_MAX_NUMBER) - 1,
};// 32K

cache_log_info g_cache_log_info = {0};

static omip_log_upload_info_para g_log_upload_info[OMIP_UPLOAD_MAX] = {
    {OMIP_DETAIL, OMIP_LOG_UPLOAD_OFF}, // gateway
    {OMIP_DETAIL, OMIP_LOG_UPLOAD_OFF}, // telephone app
};

static omip_log_level_fmt g_log_level_fmt_list[] = {
	{OMIP_EMGENCY,		 "[EMEGR]:", "emerg"},
	{OMIP_ERROR_UPLOAD,  "[ERROR]:", "error"},
	{OMIP_ERROR_FLASH,	 "[ERROR]:", ""},
	{OMIP_ERROR,		 "[ERROR]:", ""},
	{OMIP_INFO_UPLOAD,	 "[INFO]:",  "info"},
	{OMIP_INFO_FLASH,	 "[INFO]:",  ""},
	{OMIP_INFO, 		 "[INFO]:",  ""},
	{OMIP_DEBUG_UPLOAD,  "[DEBUG]:", "debug"},
	{OMIP_DEBUG,		 "[DEBUG]:", ""},
};


void omip_set_log_level(omip_log_level level)
{
	if(level > OMIP_DEBUG_UPLOAD) {
		level = OMIP_DEBUG_UPLOAD;
	}
	g_omip_log_level = level;
}


void omip_my_debug(char *str)
{
	printf("%s",str);
}


const char *omip_log_get_level_str(omip_log_level level)
{
    int fmt_index = 0;
    int fmt_list_count = sizeof(g_log_level_fmt_list) / sizeof(omip_log_level);
    for (int i = 0; i < fmt_list_count; i++) {
        if (level == g_log_level_fmt_list[i].level)
        {
            fmt_index = i;
            break;
        }
    }
    return g_log_level_fmt_list[fmt_index].fmt_str;
}

int omip_log_get_level_by_string(const char *level_name, omip_log_level *level)
{
    if (level == NULL) {
        return -1;
    }
    int fmt_list_count = sizeof(g_log_level_fmt_list) / sizeof(omip_log_level_fmt);
    for (int i = 0; i < fmt_list_count; i++) {
        if (strcmp(g_log_level_fmt_list[i].ori_str, level_name) == 0) {
            *level = g_log_level_fmt_list[i].level;
            return 0;
        }
    }
    return -1;
}

void omip_set_upload_log_level(omip_log_level level, omip_log_upload_direction direction)
{
    g_log_upload_info[direction].upload_log_level = level;
}

unsigned int omip_flash_sector_base(unsigned int addr)
{
    return ((addr) & (~OMIP_FLASH_SECTOR_MASK)); /* get the first sector address of addr */
}

unsigned int *omip_get_start_addr_by_type(omip_log_record_type type)
{
    if (type == OMIP_LOG_RECORD_CACHE) {
        return &g_start_addr_cache;
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return &g_start_addr_flash;
    }
    return NULL;
}

zone_info *omip_get_log_buffer_zone(zone_id id)
{
    if (id == g_log_buffer_zone_info.id) {
        return (zone_info *) &g_log_buffer_zone_info;
    }
    return NULL;
}

zone_info *omip_get_zone_by_type(zone_id id, omip_log_record_type type)
{
    if (type == OMIP_LOG_RECORD_CACHE) {
        return omip_get_log_buffer_zone(id);
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return mcu_get_flash_zone(id);
    }
    return NULL;
}

int omip_erase_log_buffer(zone_id id, int length)
{
    zone_info *zone_info_tmp = omip_get_log_buffer_zone(id);
    if (zone_info_tmp == NULL)
    {
        omip_my_debug("omip erase log buffer get zone\n");
        return -1;
    }

    if(length <= 0)
    {
        omip_my_debug("omip erase log buffer length invalid\n");
        return -1;
    }

    if ((zone_info_tmp->start_address + length - 1) > zone_info_tmp->end_address)
    {
        omip_my_debug("omip erase log buffer length is out of range\n");
        return -1;
    }
	if(NULL == g_omip_log_buffer) {
        omip_my_debug("g_omip_log_buffer is null\n");
        return -1;
	}

    uint32_t sector_addr = zone_info_tmp->start_address;
    uint32_t sector_num = length / OMIP_FLASH_SECTOR_SIZE + ((length % OMIP_FLASH_SECTOR_SIZE) == 0 ? 0 : 1);
    uint32_t i = 0;

    for (i = 0; i < sector_num; i++) {
        (void)memset_s(sector_addr + g_omip_log_buffer + OMIP_FLASH_SECTOR_SIZE * i,
                       OMIP_FLASH_SECTOR_SIZE, 0, OMIP_FLASH_SECTOR_SIZE);
    }
    return 0;
}


int omip_erase_by_type(zone_id id, int length, omip_log_record_type type)
{
   if (type == OMIP_LOG_RECORD_CACHE) {
        return omip_erase_log_buffer(id, length);
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return mcu_erase_flash(id, length);
    }
    return -1;
}

int omip_read_log_buffer(zone_id id, unsigned int address, uint8_t* buffer, unsigned int length)
{
    zone_info *zone_info_tmp = omip_get_log_buffer_zone(id);

    if (zone_info_tmp == NULL)
    {
        omip_my_debug("omip read log buffer get zone failed\n");
        return -1;
    }

    if ((address < zone_info_tmp->start_address) || ((address + length - 1) > zone_info_tmp->end_address))
    {
        omip_my_debug("omip read log buffer length is out of range\n");
        return -1;
    }

    if ((buffer == NULL) || (length <= 0))
    {
        omip_my_debug("omip read log buffer buffer or length is invalid\n");
        return -1;
    }

    if (memcpy_s(buffer, length, address + g_omip_log_buffer, length) != EOK)
    {
        omip_my_debug("omip read log buffer read flash failed\n");
        return -1;
    }
    return 0;
}


int omip_read_by_type(zone_id id, unsigned int address, uint8_t* buffer, unsigned int length,
                      omip_log_record_type type)
{
    if (type == OMIP_LOG_RECORD_CACHE) {
        return omip_read_log_buffer(id, address, buffer, length);
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return mcu_read_flash(id, address, buffer, length);
    }
    return -1;
}


int omip_log_get_head(uint32_t head_addr, omip_log_sector_head *head, omip_log_record_type type)
{
    zone_info *logrecord_zone = NULL;
    logrecord_zone = omip_get_zone_by_type(LOGRECORD_ZONE, type);
    if (logrecord_zone == NULL) {
        omip_my_debug("zone_al_get(LOGRECORD_ZONE) failed\n");
        return -1;
    }

    uint32_t head_len = sizeof(omip_log_sector_head);
    if ((head_addr < logrecord_zone->start_address) || (head_addr > logrecord_zone->end_address)) {
        omip_my_debug("head_addr invalid\n");
        return -1;
    }

    if (head == NULL) {
        omip_my_debug("param head is null\n");
        return -1;
    }

    (void)memset_s(head, head_len, 0, head_len);
    if (omip_read_by_type(logrecord_zone->id, head_addr, (unsigned char *)head, head_len, type) != 0) {
        omip_my_debug("Read stream failed\n");
        return -1;
    }
    return 0;
}

int omip_erase_sector_log_buffer(zone_id id, unsigned int address, int length)
{
    zone_info *zone_info_tmp = omip_get_log_buffer_zone(id);
    if (zone_info_tmp == NULL)
    {
        omip_my_debug("omip erase sector log buffer get zone failed\n");
        return -1;
    }
    if(length <= 0)
    {
        omip_my_debug("omip erase sector log buffer length is invalid\n");
        return -1;
    }
    if ((address < zone_info_tmp->start_address) || ((address + length - 1) > zone_info_tmp->end_address))
     {
        omip_my_debug("omip erase sector log buffer length is out of range\n");
        return -1;
    }
    (void)memset_s(address + g_omip_log_buffer, OMIP_FLASH_SECTOR_SIZE, 0, OMIP_FLASH_SECTOR_SIZE);
    return 0;
}

int omip_write_log_buffer(zone_id id, unsigned int address, const uint8_t* buffer, unsigned int length)
{
    zone_info *zone_info_tmp = omip_get_log_buffer_zone(id);

    if (zone_info_tmp == NULL)
    {
         omip_my_debug("omip write log buffer get zone failed\n");
         return -1;
    }

    if ((buffer == NULL) || (length <= 0))
    {
        omip_my_debug("omip write log buffer or length is invalid\n");
        return -1;
    }

    if ((address < zone_info_tmp->start_address) || ((address + length - 1) > zone_info_tmp->end_address))
    {
        omip_my_debug("omip write log buffer length is out of range\n");
        return -1;
    }

    unsigned int w_address = address + (unsigned int)g_omip_log_buffer; /* map to real buffer address */
    if (memcpy_s((void *)w_address, length, buffer, length) != EOK)
    {
        omip_my_debug("omip write log buffer write flash failed\n");
        return -1;
    }
    return 0;
}


int omip_erase_sector_by_type(zone_id id, unsigned int address, int length, omip_log_record_type type)
{
    if (type == OMIP_LOG_RECORD_CACHE) {
        return omip_erase_sector_log_buffer(id, address, length);
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return mcu_erase_sector_flash(id, address, length);
    }
    return -1;
}

int omip_write_by_type(zone_id id, unsigned int address, const uint8_t* buffer, unsigned int length,
                       omip_log_record_type type)
{
    if (type == OMIP_LOG_RECORD_CACHE) {
        return omip_write_log_buffer(id, address, buffer, length);
    } else if (type == OMIP_LOG_RECODE_FLASH) {
        return mcu_write_flash(id, address, buffer, length);
    }
    return -1;
}


int omip_log_set_head(uint32_t head_addr, omip_log_sector_head *head, omip_log_record_type type)
{
    zone_info *logrecord_zone = NULL;
    logrecord_zone = omip_get_zone_by_type(LOGRECORD_ZONE, type);
    int ret;
    if (logrecord_zone == NULL) {
        omip_my_debug("zone_al_get(LOGRECORD_ZONE) failed\n");
        return -1;
    }

    if ((head_addr < logrecord_zone->start_address) || (head_addr > logrecord_zone->end_address)) {
        omip_my_debug(" set head_addr invalid\n");
        return -1;
    }

    if (head == NULL) {
        omip_my_debug("param head is null\n");
        return -1;
    }

    static uint8_t g_hlink_flash_cache[OMIP_FLASH_SECTOR_SIZE] = {0};

    (void)memset_s(g_hlink_flash_cache, OMIP_FLASH_SECTOR_SIZE, 0, OMIP_FLASH_SECTOR_SIZE);

    if (omip_read_by_type(logrecord_zone->id, head_addr, g_hlink_flash_cache, OMIP_FLASH_SECTOR_SIZE, type) != 0) {
        omip_my_debug("read flash failed\n");
        return -1;
    }
    ret = memcpy_s(g_hlink_flash_cache, sizeof(g_hlink_flash_cache), head, sizeof(omip_log_sector_head));
    if (ret != EOK) {
        omip_my_debug("log set head memcpy_s failed\n");
        return ret;
    }

    if (omip_erase_sector_by_type(logrecord_zone->id, head_addr, OMIP_FLASH_SECTOR_SIZE, type) != 0) {
        omip_my_debug("earse log flash failed\n");
        return -1;
    }

    if (omip_write_by_type(logrecord_zone->id, head_addr, (unsigned char *)g_hlink_flash_cache,
                           OMIP_FLASH_SECTOR_SIZE, type) != 0) {
        omip_my_debug("Write stream failed\n");
        return -1;
    }
    return 0;
}


int omip_log_write_invalid_proc(zone_info *logrecord_zone, omip_log_sector_head *head, omip_log_record_type type)
{
    char debug_info[OMIP_DEBUG_INFO_LEN] = {0};
    if ((logrecord_zone == NULL) || (head == NULL)) {
        omip_my_debug("invalid parameter in write invalid process!\n");
        return -1;
    }

    if (head->flag == OMIP_VALID_LOG_FLAG) {
        return 0;
    }
    unsigned int *start_addr = omip_get_start_addr_by_type(type);
    if (omip_erase_sector_by_type(logrecord_zone->id, omip_flash_sector_base(*start_addr),
                                  OMIP_FLASH_SECTOR_SIZE, type) != 0) {
        if (sprintf_s(debug_info, sizeof(debug_info), "earse sector flash failed, addr = 0x%x\n",
                      omip_flash_sector_base(*start_addr)) >= 0) {
            omip_my_debug(debug_info);
        } else {
            omip_my_debug("earse sector flash failed\n");
        }
        return -1;
    }

    head->flag = OMIP_VALID_LOG_FLAG;
    head->logsize = 0;
    head->status = OMIP_SECTOR_NOT_FULL;
    omip_log_set_head(omip_flash_sector_base(*start_addr), head, type);
    return 0;
}

cache_log_info * get_cache_log_info()
{
	return &g_cache_log_info;
}

int omip_read_cache_log(uint8_t *buff, uint8_t *addr, uint16_t len)
{
	if(buff == NULL) {
		printf("[%s:%d]Invalid parameter\r\n", __FUNCTION__, __LINE__);
		return -1;
	}
	if(addr < g_cache_log_info.start_address || addr+len > g_cache_log_info.last_address) {
		printf("read address out of bounds\r\n");
		return -1;
	}
	memcpy(buff, addr, len);
	return len;
}
int omip_cache_log_record(char *log_data, unsigned short log_len)
{
	if(NULL == log_data || log_len == 0 || g_cache_log_info.start_address == NULL) {
		printf("[%s:%d]Invalid parameter\r\n", __FUNCTION__, __LINE__);
		return -1;
	}
	if(g_cache_log_info.last_address < g_cache_log_info.start_address ||
		g_cache_log_info.last_address > g_cache_log_info.end_address) {
		
		printf("last_address out of bounds, last_address restart\r\n");
		g_cache_log_info.last_address = g_cache_log_info.start_address;
		memset(g_cache_log_info.start_address, 0, OMIP_FLASH_SECTOR_SIZE * OMIP_LOG_BUFFER_MAX_NUMBER);
	}
	
	if(g_cache_log_info.last_address + log_len > g_cache_log_info.end_address) {
		g_cache_log_info.last_address = g_cache_log_info.start_address;
		printf("cache log is full, last_address restart\r\n");
		memset(g_cache_log_info.start_address, 0, OMIP_FLASH_SECTOR_SIZE * OMIP_LOG_BUFFER_MAX_NUMBER);
	}
	memcpy(g_cache_log_info.last_address, log_data, log_len);
	g_cache_log_info.last_address += log_len;
	return 0;
}

int omip_log_record(const char *log_data, unsigned short log_len, omip_log_record_type type)
{
    char debug_info[OMIP_DEBUG_INFO_LEN] = {0};
    uint32_t log_left_len = log_len;
    uint32_t sector_left_len;
    omip_log_sector_head head = { 0 };
	char *record_type[] = {"cache", "flash"};
    zone_info *logrecord_zone = omip_get_zone_by_type(LOGRECORD_ZONE, type);
    if (logrecord_zone == NULL) {
        omip_my_debug("zone_al_get(FILEMNGR_ZONE) failed\n");
        return -1;
    }

    unsigned int *start_addr = omip_get_start_addr_by_type(type);
    if (start_addr == NULL) {
        omip_my_debug("get start addr failed\r\n");
        return -1;
    }
    if (*start_addr == 0) {
        *start_addr = logrecord_zone->start_address;
    }

BEGIN:

    if (*start_addr > logrecord_zone->end_address) {
		printf("%s log area is full, from begin start\r\n", record_type[type]);
        *start_addr = logrecord_zone->start_address;
        omip_erase_by_type(logrecord_zone->id, logrecord_zone->end_address - logrecord_zone->start_address, type);
    }
    omip_log_get_head(omip_flash_sector_base(*start_addr), &head, type);
    int ret = omip_log_write_invalid_proc(logrecord_zone, &head, type);
    if (ret != 0) {
        return ret;
    }

    if (head.status == OMIP_SECTOR_FULL) {
		printf("%s sector(0x%x) is full, find next sector\r\n", record_type[type], omip_flash_sector_base(*start_addr));
        *start_addr = omip_flash_sector_base(*start_addr) + OMIP_FLASH_SECTOR_SIZE;
        goto BEGIN;
    }
    *start_addr = omip_flash_sector_base(*start_addr) + sizeof(omip_log_sector_head) + head.logsize;
    //sector_left_len = OMIP_FLASH_SECTOR_SIZE - (*start_addr % OMIP_FLASH_SECTOR_SIZE);
	sector_left_len = OMIP_FLASH_SECTOR_SIZE - (sizeof(omip_log_sector_head) + head.logsize);

    if (sector_left_len < log_left_len) {
        if (sprintf_s(debug_info, sizeof(debug_info), "%s current sector [0x%x] is not enough to store %d bytes\r\n",
                     record_type[type], omip_flash_sector_base(*start_addr), log_left_len) >= 0) {
            omip_my_debug(debug_info);
        } else {
            omip_my_debug("current sector is not enough to store\r\n");
        }

        head.status = OMIP_SECTOR_FULL;
        omip_log_set_head(omip_flash_sector_base(*start_addr), &head, type);
        *start_addr = omip_flash_sector_base(*start_addr) + OMIP_FLASH_SECTOR_SIZE;
        goto BEGIN;
    }
    if (omip_write_by_type(logrecord_zone->id, *start_addr, (const unsigned char *)log_data,
                              log_left_len, type) != 0) {
        (void)memset_s(debug_info, sizeof(debug_info), 0, sizeof(debug_info));
        if (sprintf_s(debug_info, sizeof(debug_info), "write log to flash [0x%08x] failed!\r\n", start_addr) >= 0) {
            omip_my_debug(debug_info);
        } else {
            omip_my_debug("write log to flash failed!\r\n");
        }

        return -1;
    }
    head.logsize += log_left_len;
    omip_log_set_head(omip_flash_sector_base(*start_addr), &head, type);
    *start_addr += log_left_len;
    return 0;
}

void mcu_set_time_by_sec(unsigned long long sec)
{
	g_time_utc_sec = sec;
    return;
}

unsigned long long mcu_get_time_by_sec(void)
{
    return g_time_utc_sec;
}

void omip_mcu_localtime(mcu_tm *tm)
{
    unsigned long long sec = mcu_get_time_by_sec();
	sec += (LOS_Tick2MS(LOS_TickCountGet()) / 1000);
    offset_time(sec, SECS_PER_HOUR * 8, tm); /* timezone beijing +8h */
}


int omip_create_log_header_default(char *buf, unsigned short buf_len, omip_log_level level)
{
    int log_header_len = 0;
    mcu_tm tm;
    omip_mcu_localtime(&tm);
    const char *fmt_str = omip_log_get_level_str(level);
    log_header_len = snprintf_s(buf, buf_len, buf_len - 1,
                                "[%d-%02d-%02d %02d:%02d:%02d][MCU]%s",
                                tm.tm_year, tm.tm_mon, tm.tm_mday,
                                tm.tm_hour, tm.tm_min, tm.tm_sec, fmt_str);
    return log_header_len;
}


void omip_device_log_upload_gateway(char *omip_print_buf)
{
    return;
}


void omip_log_upload_proc(omip_log_level level)
{
    // gateway upload
    if (g_log_upload_info[OMIP_UPLOAD_GATEWAY].upload_log_switch == OMIP_LOG_UPLOAD_ON) {
        if ((g_log_upload_info[OMIP_UPLOAD_GATEWAY].upload_log_level == OMIP_MAX) ||
            (g_log_upload_info[OMIP_UPLOAD_GATEWAY].upload_log_level == level)) {
                omip_device_log_upload_gateway(g_omip_print_buf);
            }
    }
    // app upload
    if (g_log_upload_info[OMIP_UPLOAD_APP].upload_log_switch == OMIP_LOG_UPLOAD_ON) {
        omip_log_level upload_log_level = g_log_upload_info[OMIP_UPLOAD_APP].upload_log_level;
        if (upload_log_level == OMIP_MAX) {
            if ((level != OMIP_ERROR_UPLOAD) && (level != OMIP_INFO_UPLOAD) && (level != OMIP_DEBUG_UPLOAD)) {
                return;
            }
        } else {
            if (upload_log_level != level) {
                return;
            }
        }
        omip_device_log_upload_app(g_omip_print_buf);
    }
    return;
}


void omip_printf(omip_log_level level, const char *format, ...)
{
    int ret = -1;
    va_list argList;
    int log_header = 0;
	static osal_mutex_t mutexPrint =cn_mutex_invalid;
	if(mutexPrint ==cn_mutex_invalid) osal_mutex_create(&mutexPrint);
    if(level > g_omip_log_level) return;


	(void)osal_mutex_lock(mutexPrint);
    (void)memset_s(g_omip_print_buf, sizeof(g_omip_print_buf), 0, sizeof(g_omip_print_buf));
    ret = omip_create_log_header_default(g_omip_print_buf, sizeof(g_omip_print_buf), level);
    if((ret >= 0) && (ret < (int)sizeof(g_omip_print_buf)))
    {
        log_header += ret;
    }

    va_start(argList, format);
    ret = vsprintf_s(g_omip_print_buf+log_header, sizeof(g_omip_print_buf)-1-log_header, format, argList);
    va_end(argList);
    if(ret == -1)
    {
        omip_my_debug("OMIP DEBUG ERROR!!!\r\n");
		osal_mutex_unlock(mutexPrint);
        return;
    }
    omip_my_debug(g_omip_print_buf);

    if(level <= OMIP_INFO)
    {
        if (g_omip_log_buffer != NULL) {
            /* cache record info and smaller than info level log */
            //omip_log_record(g_omip_print_buf, strlen(g_omip_print_buf), OMIP_LOG_RECORD_CACHE);
            //omip_cache_log_record(g_omip_print_buf, strlen(g_omip_print_buf));
        }
    }

    if (level <= OMIP_ERROR)
    {
        /* flash record error and smaller than error level log */
        //omip_log_record(g_omip_print_buf, strlen(g_omip_print_buf), OMIP_LOG_RECODE_FLASH);
    }
	
	omip_log_upload_proc(level);
	osal_mutex_unlock(mutexPrint);

}

void omip_print_io_bytes(const unsigned char *pp, unsigned short len, unsigned char sr, unsigned char node_id)
{
    omip_log_level debug = OMIP_DEBUG;
    if(sr)	omip_printf(debug,"send frame(len:%d) to pyhs node(id:%d):\r\n",len, node_id);
    else	omip_printf(debug,"recv frame(len:%d) from pyhs node(id:%d):\r\n",len, node_id);
    for(int i = 0; i< len; i+= 16)
    {
        if(i+16 <= len) {
            omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10],pp[i+11],pp[i+12],pp[i+13],
                pp[i+14],pp[i+15]);
        }
        else
        {
            switch(len - i)
            {
                case 15:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10],pp[i+11],pp[i+12],pp[i+13],
                pp[i+14]);
                break;
                case 14:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10],pp[i+11],pp[i+12],pp[i+13]);
                break;
                case 13:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10],pp[i+11],pp[i+12]);
                break;
                case 12:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10],pp[i+11]);
                break;
                case 11:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9],pp[i+10]);
                break;
                case 10:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8],pp[i+9]);
                break;
                case 9:
                omip_printf(debug,"%x %x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7],pp[i+8]);
                break;
                case 8:
                omip_printf(debug,"%x %x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6],
                pp[i+7]);
                break;
                case 7:
                omip_printf(debug,"%x %x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5],pp[i+6]);
                break;
                case 6:
                omip_printf(debug,"%x %x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4],pp[i+5]);
                break;
                case 5:
                omip_printf(debug,"%x %x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3],pp[i+4]);
                break;

                case 4:
                omip_printf(debug,"%x %x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2],pp[i+3]);
                break;

                case 3:
                omip_printf(debug,"%x %x %x\r\n",
                pp[i+0],pp[i+1],pp[i+2]);
                break;

                case 2:
                omip_printf(debug,"%x %x\r\n",
                pp[i+0],pp[i+1]);
                break;

                case 1:
                omip_printf(debug,"%x\r\n",
                pp[i+0]);
                break;
                default:
                    break;
            }
        }
    }
    omip_printf(debug,"\r\n");
}


